#ifndef VALIDMOVE_H_
#define VALIDMOVE_H_

#include "gameboard.h"
#include "mainwindow.h"
#include "global.h"

bool MainWindow::validMove(int oldx, int oldy, int newx, int newy) {  // relative to board, not uiBoard
  int mutator = 1;
  if (player == BLACK)
    mutator = -1;
  // TODO: implement logic here
  int pieceType = board->getType(oldx, oldy);
  // TODO: implement castling check here
  if (board->getType(newx, newy) >= 0 && board->getColor(newx, newy) == player) // if the position has one of the player's other pieces, then no further check is needed
    return false;
  switch (pieceType) {
    case PAWN:
      if (board->atInitial(oldx, oldy) && newx == oldx && mutator*(newy-oldy) > 0 && mutator*(newy-oldy) <= 2 && board->getType(newx, newy) < 0)  // can player move initial 2?
        if (board->getType(oldx, oldy+mutator) < 0) // is the one that it must skip over empty?
          return true;
      if (!board->atInitial(oldx, oldy) && newx == oldx && mutator*(newy-oldy) > 0 && mutator*(newy-oldy) <= 1 && board->getType(newx, newy) < 0) // move just 1 square if not in initial spot
        return true;
      if ((newx-oldx == 1 || newx-oldx == -1) && mutator*(newy-oldy) == 1 && board->getColor(newx, newy) != player && board->getType(newx, newy) >= 0) {  // capture opponent's piece
        removePiece(newx, newy);
        return true;
      }
      break;
    case ROOK:
      if (oldx != newx && oldy != newy) // rook can't move diagonally
        return false;
      if (oldy == newy) { // move horizontally
        if (newx > oldx) {  // move right
          for (int i = 1; i < newx-oldx; i++)
            if (board->getType(oldx+i, newy) >= 0)  // rook can't jump over pieces
              return false;
          if (board->getColor(newx, newy) >= 0) // capture opponent's piece
            removePiece(newx, newy);
          return true;
        }
        else {  // move left
          for (int i = 1; i < oldx-newx; i++)
            if (board->getType(oldx-i, newy) >= 0)  // rook can't jump over pieces
              return false;
          if (board->getColor(newx, newy) >= 0) // capture opponent's piece
              removePiece(newx, newy);
          return true;
        }
      }
      else {  // move vertically
        if (newy > oldy) {  // move up
          for (int i = 1; i < newy-oldy; i++)
            if (board->getType(newx, oldy+i) >= 0)  // can't jump over pieces
              return false;
          if (board->getColor(newx, newy) >= 0) // capture opponent's piece
            removePiece(newx, newy);
          return true;
        }
        else {  // move down
          for (int i = 1; i < oldy-newy; i++)
            if (board->getType(newx, oldy-i) >= 0)  // can't jump over pieces
              return false;
          if (board->getColor(newx, newy) >= 0)  // capture opponent's piece
            removePiece(newx, newy);
          return true;
        }
      }
      break;
    case BISHOP:
      if (newx == oldx || newy == oldy) // to prevent divide by 0
        return false;
      if ((newx-oldx) / (newy-oldy) != -1 && (newx-oldx) / (newy-oldy) != 1) {  // can only move diagonally
        return false;
      }
      else {  // move diagonally
        if (newx-oldx == newy-oldy) { // move up right
          for (int i = 1; i < newy-oldy; i++)
            if (board->getType(oldx+i, oldy+i) >= 0)  // can't jump over pieces
              return false;
          if (board->getColor(newx, newy) >= 0)  // capture opponent's piece
            removePiece(newx, newy);
          return true;
        }
        else if (oldx-newx == newy-oldy) {  // move up left
          for (int i = 1; i < newy-oldy; i++)
            if (board->getType(oldx-i, oldy+i) >= 0)  // can't jump over pieces
              return false;
          if (board->getColor(newx, newy) >= 0)  // capture opponent's piece
            removePiece(newx, newy);
          return true;
        }
        else if (newx-oldx == oldy-newy) {  // move down right
          for (int i = 1; i < newx-oldx; i++)
            if (board->getType(oldx+i, oldy-i) >= 0)  // can't jump over pieces
              return false;
          if (board->getColor(newx, newy) >= 0)  // capture opponent's piece
            removePiece(newx, newy);
          return true;
        }
        else if (oldx-newx == oldy-newy) {  // move down left
          for (int i = 1; i < oldy-newy; i++)
            if (board->getType(oldx-i, oldy-i) >= 0)  // can't jump over pieces
              return false;
          if (board->getColor(newx, newy) >= 0)  // capture opponent's piece
            removePiece(newx, newy);
          return true;
        }
      }
      break;
    case KNIGHT:
      if (oldx == newx || oldy == newy) // can't move in straight lines
        return false;
      if (newx-oldx == 2 && newy-oldy == 1) { // right up
        if (board->getType(newx, newy) >= 0)
          removePiece(newx, newy);  // capture opponents piece
        return true;
      }
      if (newx-oldx == 1 && newy-oldy == 2) { // up right
        if (board->getType(newx, newy) >= 0)
          removePiece(newx, newy);
        return true;
      }
      if (oldx-newx == 1 && newy-oldy == 2) { // up left
        if (board->getType(newx, newy) >= 0)
          removePiece(newx, newy);
        return true;
      }
      if (oldx-newx == 2 && newy-oldy == 1) { // left up
        if (board->getType(newx, newy) >= 0)
          removePiece(newx, newy);
        return true;
      }
      if (oldx-newx == 2 && oldy-newy == 1) { // left down
        if (board->getType(newx, newy) >= 0)
          removePiece(newx, newy);
        return true;
      }
      if (oldx-newx == 1 && oldy-newy == 2) { // down left
        if (board->getType(newx, newy) >= 0)
          removePiece(newx, newy);
        return true;
      }
      if (newx-oldx == 1 && oldy-newy == 2) { // down right
        if (board->getType(newx, newy) >= 0)
          removePiece(newx, newy);
        return true;
      }
      if (newx-oldx == 2 && oldy-newy == 1) { // right down
        if (board->getType(newx, newy) >= 0)
          removePiece(newx, newy);
        return true;
      }
      break;
    case KING:
      if (newx-oldx == 1 && newy == oldy) {  // move right
        if (board->getType(newx, newy) >= 0)
          removePiece(newx, newy);
        return true;
      }
      else if (newx-oldx == 1 && newy-oldy == 1) {  // move up right
        if (board->getType(newx, newy) >= 0)
          removePiece(newx, newy);
        return true;
      }
      else if (newx == oldx && newy-oldy == 1) {  // move up
        if (board->getType(newx, newy) >= 0)
          removePiece(newx, newy);
        return true;
      }
      else if (oldx-newx == 1 && newy-oldy == 1) {  // move up left
        if (board->getType(newx, newy) >= 0)
          removePiece(newx, newy);
        return true;
      }
      else if (oldx-newx == 1 && newy == oldy) {  // move left
        if (board->getType(newx, newy) >= 0)
          removePiece(newx, newy);
        return true;
      }
      else if (oldx-newx == 1 && oldy-newy == 1) {  // move down left
        if (board->getType(newx, newy) >= 0)
          removePiece(newx, newy);
        return true;
      }
      else if (newx == oldx && oldy-newy == 1) {  // move down
        if (board->getType(newx, newy) >= 0)
          removePiece(newx, newy);
        return true;
      }
      else if (newx-oldx == 1 && oldy-newy == 1) {  // move down right
        if (board->getType(newx, newy) >= 0)
          removePiece(newx, newy);
        return true;
      }
      break;
    case QUEEN:
      if (oldy == newy) { // move horizontally
        if (newx > oldx) {  // move right
          for (int i = 1; i < newx-oldx; i++)
            if (board->getType(oldx+i, newy) >= 0)  //can't jump over pieces
              return false;
          if (board->getColor(newx, newy) >= 0)  // capture opponent's piece
            removePiece(newx, newy);
          return true;
        }
        else {  // move left
          for (int i = 1; i < oldx-newx; i++)
            if (board->getType(oldx-i, newy) >= 0)  // can't jump over pieces
              return false;
          if (board->getColor(newx, newy) >= 0)  // capture opponent's piece
            removePiece(newx, newy);
          return true;
        }
      }
      else if (oldx == newx) {  // move vertically
        if (newy > oldy) {  // move up
          for (int i = 1; i < newy-oldy; i++)
            if (board->getType(newx, oldy+i) >= 0)  // jump over pieces
              return false;
          if (board->getColor(newx, newy) >= 0)  // capture opponent's piece
            removePiece(newx, newy);
          return true;
        }
        else {  // move down
          for (int i = 1; i < oldy-newy; i++)
            if (board->getType(newx, oldy-i) >= 0)  // jump over pieces
              return false;
          if (board->getColor(newx, newy) >= 0)  // capture opponent's piece
            removePiece(newx, newy);
          return true;
        }
      }
      else if (newx-oldx == newy-oldy) { // move up right
          for (int i = 1; i < newy-oldy; i++)
            if (board->getType(oldx+i, oldy+i) >= 0)  // can't jump over pieces
              return false;
          if (board->getColor(newx, newy) >= 0)  // capture opponent's piece
            removePiece(newx, newy);
          return true;
      }
      else if (oldx-newx == newy-oldy) {  // move up left
        for (int i = 1; i < newy-oldy; i++)
          if (board->getType(oldx-i, oldy+i) >= 0)  // can't jump over pieces
            return false;
        if (board->getColor(newx, newy) >= 0)  // capture opponent's piece
          removePiece(newx, newy);
        return true;
      }
      else if (newx-oldx == oldy-newy) {  // move down right
        for (int i = 1; i < newx-oldx; i++)
          if (board->getType(oldx+i, oldy-i) >= 0)  // can't jump over pieces
            return false;
        if (board->getColor(newx, newy) >= 0)  // capture opponent's piece
          removePiece(newx, newy);
        return true;
      }
      else if (oldx-newx == oldy-newy) {  // move down left
        for (int i = 1; i < oldy-newy; i++)
          if (board->getType(oldx-i, oldy-i) >= 0)  // can't jump over pieces
            return false;
        if (board->getColor(newx, newy) >= 0)  // capture opponent's piece
          removePiece(newx, newy);
        return true;
      }
      break;
  } //end switch
  return false;
}

#endif
